package com.cargohu.aishouyu.member.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cargohu.aishouyu.auth.util.LoginUtil;
import com.cargohu.aishouyu.framework.constant.RedisKey;
import com.cargohu.aishouyu.framework.exception.BusinessException;
import com.cargohu.aishouyu.framework.page.OrderByItem;
import com.cargohu.aishouyu.framework.page.Paging;
import com.cargohu.aishouyu.framework.service.impl.BaseServiceImpl;
import com.cargohu.aishouyu.member.dto.MemberSignAddDTO;
import com.cargohu.aishouyu.member.dto.MemberSignUpdateDTO;
import com.cargohu.aishouyu.member.entity.MemberSign;
import com.cargohu.aishouyu.member.mapper.MemberSignMapper;
import com.cargohu.aishouyu.member.req.MemberSignRequest;
import com.cargohu.aishouyu.member.resp.MemberSignDetailVo;
import com.cargohu.aishouyu.member.resp.MemberSignResponse;
import com.cargohu.aishouyu.member.service.MemberSignService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户签到记录 服务实现类
 *
 * @author yww
 * @since 2023-11-29
 */
@Slf4j
@Service
public class MemberSignServiceImpl extends BaseServiceImpl<MemberSignMapper, MemberSign> implements MemberSignService {

    @Autowired
    private MemberSignMapper memberSignMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addMemberSign(MemberSignAddDTO memberSignAddDTO) throws Exception {
        String signRedisKey = String.format(RedisKey.MEMBER_SIGN,
                LoginUtil.getUserId(), DateUtil.formatDate(new Date()));
        String signed = (String) redisTemplate.opsForValue().get(signRedisKey);
        if (StrUtil.isNotEmpty(signed)) {
            throw new BusinessException("今日已签到");
        }
        MemberSign memberSign = new MemberSign();
        memberSignAddDTO.setSignTime(DateUtil.date());
        BeanUtils.copyProperties(memberSignAddDTO, memberSign);
        boolean result = save(memberSign);
        redisTemplate.opsForValue().set(signRedisKey, "1", Duration.ofDays(1));
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateMemberSign(MemberSignUpdateDTO memberSignUpdateDTO) throws Exception {
        Long id = memberSignUpdateDTO.getId();
        MemberSign memberSign = getById(id);
        if (memberSign == null) {
            throw new BusinessException("用户签到记录不存在");
        }
        BeanUtils.copyProperties(memberSignUpdateDTO, memberSign);
        return updateById(memberSign);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteMemberSign(Long id) throws Exception {
        return removeById(id);
    }

    @Override
    public MemberSignDetailVo getMemberSignById(Long id) throws Exception {
        return memberSignMapper.getMemberSignById(id);
    }

    @Override
    public Paging<MemberSignResponse> getMemberSignList(MemberSignRequest memberSignRequest) throws Exception {
        handlePage(memberSignRequest, OrderByItem.desc("id"));
        List<MemberSignResponse> list = memberSignMapper.getMemberSignList(memberSignRequest);
        Paging<MemberSignResponse> paging = new Paging<>(list);
        return paging;
    }

    @Override
    public List<Integer> getMemberWeekSignHistory(Long memberId) throws Exception {
        List<Integer> memberSignDetailList = new ArrayList<>(Arrays.asList(0, 0, 0, 0, 0, 0, 0));
        // 获取本周开始第一天
        DateTime beginOfWeek = DateUtil.beginOfWeek(new Date(), true);
        // 获取本周结束第一天
        DateTime endOfWeek = DateUtil.endOfWeek(new Date(), true);
        // 查询本周签到记录
        List<MemberSign> memberSignList = baseMapper
                .selectList(Wrappers.<MemberSign>query().lambda().eq(MemberSign::getMemberId, memberId)
                .between(MemberSign::getSignTime, beginOfWeek, endOfWeek).orderByDesc(MemberSign::getSignTime));
        if (!CollectionUtils.isEmpty(memberSignList)) {
            List<Date> signDateList =  memberSignList.stream().map(MemberSign::getSignTime).collect(Collectors.toList());
            signDateList.forEach(date -> {
                int day = DateUtil.dayOfWeek(date) - 2;
                memberSignDetailList.set(day == -1 ? 6 : day, 1);
            });
        }
        return memberSignDetailList;
    }

}
